<?php

use Phalcon\Config\Adapter\Ini as ConfigIni;
use Phalcon\Crypt;
use Phalcon\Flash\Direct as Flash;
use Phalcon\Logger\Adapter\File as FileAdapter;
use Phalcon\Mvc\Collection\Manager;
use Phalcon\Mvc\Model\Metadata\Memory as MetaDataAdapter;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Php as PhpEngine;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Session\Adapter\Files as SessionAdapter;

/**
 * Shared configuration service
 */
$di->setShared('config', function () {
    $config = new ConfigIni(APP_PATH . '/config/config.default.ini', INI_SCANNER_NORMAL);
    if (is_readable(APP_PATH . '/config/config.' . ENVIRONMENT . '.ini')) {
        $override = new ConfigIni(APP_PATH . '/config/config.' . ENVIRONMENT . '.ini');
        $config->merge($override);
    }
    return $config;
});

//增加控制器和方法找不到后指向error404
$di->set('dispatcher', function () use ($di) {
    $eventsManager = new \Phalcon\Events\Manager();
    $eventsManager->attach("dispatch", function ($event, $dispatcher, $exception) {
        if ($event->getType() == 'beforeException') {
            /*echo $exception->getCode();
            echo \Phalcon\Dispatcher::EXCEPTION_ACTION_NOT_FOUND;
            die;*/
            switch ($exception->getCode()) {
                case \Phalcon\Dispatcher::EXCEPTION_HANDLER_NOT_FOUND:
                case \Phalcon\Dispatcher::EXCEPTION_ACTION_NOT_FOUND:
                    $dispatcher->forward(array(
                        'controller' => 'index',
                        'action'     => 'error404',
                    ));
                    return false;
            }
        }
    });
    $security = new Security($di);
    $eventsManager->attach('dispatch', $security);
    $dispatcher = new \Phalcon\Mvc\Dispatcher();
    $dispatcher->setEventsManager($eventsManager);
    return $dispatcher;
});

/**
 * The URL component is used to generate all kind of urls in the application
 */
$di->setShared('url', function () {
    $config = $this->getConfig();

    $url = new UrlResolver();
    $url->setBaseUri($config->application->baseUri);

    return $url;
});

/**
 * Setting up the view component
 */
$di->setShared('view', function () {
    $config = $this->getConfig();

    $view = new View();
    $view->setDI($this);
    $view->setViewsDir($config->application->viewsDir);

    $view->registerEngines([
        '.volt'  => function ($view) {
            $config = $this->getConfig();

            $volt = new VoltEngine($view, $this);

            $volt->setOptions([
                'compiledPath'      => $config->application->cacheDir,
                'compiledSeparator' => '_',
            ]);

            $compiler = $volt->getCompiler();
            $compiler->addFunction("in_array", "in_array");

            return $volt;
        },
        '.phtml' => PhpEngine::class,

    ]);

    return $view;
});

/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$di->setShared('db', function () {
    $config   = $this->getConfig();
    $dbConfig = $config->database->toArray();
    $adapter  = $dbConfig['adapter'];
    unset($dbConfig['adapter']);

    $class = 'Phalcon\Db\Adapter\Pdo\\' . $adapter;

    return new $class($dbConfig);
});

/**
 * If the configuration specify the use of metadata adapter use it or use memory otherwise
 */
$di->setShared('modelsMetadata', function () {
    return new MetaDataAdapter();
});

/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->set('flash', function () {
    return new Flash([
        'error'   => 'alert alert-danger',
        'success' => 'alert alert-success',
        'notice'  => 'alert alert-info',
        'warning' => 'alert alert-warning',
    ]);
});

/**
 * Start the session the first time some component request the session service
 */
$di->setShared('session', function () {
    $session = new SessionAdapter();
    $session->start();

    return $session;
});

$di->setShared('redis', function () {
    $config = $this->getConfig();
    $redis  = new redis();
    $redis->connect($config->redis->host, $config->redis->port);
    return $redis;
});

$di->set('crypt', function () {
    $crypt = new Crypt();
    $crypt->setKey('#1dj8$=dp?.ak//j');
    return $crypt;
});

$di->setShared('logger', function () {
    return new FileAdapter(BASE_PATH . "/logs/logger.log");
});

stream_wrapper_register("VariableStream", "VariableStream");

class VariableStream
{
    private $string;
    private $position;
    public function stream_open($path, $mode, $options, &$opened_path)
    {
        $this->string   = substr($path, strlen('VariableStream://'));
        $this->position = 0;
        return true;
    }
    public function stream_read($count)
    {
        $ret = substr($this->string, $this->position, $count);
        $this->position += strlen($ret);
        return $ret;
    }
    public function stream_stat()
    {
    }
    public function stream_eof()
    {
    }
}
